﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using AndBurn.DDSReader;

namespace DnPakExplorer.Forms {
	public partial class InfoOverlayForm : Form {

		private bool ToShow = false;

		List<DrawingBlock> mTexts;

		ImageBlock mDivider;
		Image mBackgroundImage;

		private Font mItemNameFont;

		private List<DrawingBlock> mTmpContent;
		private Point mTmpStartPoint;
		private IItem mItem;
		private Skill mSkill;
		private ItemIcon mItemIcon;
		private Point mStartOffset = new Point(12, 12);
		private Size mPageSize = new Size(190, 650);
		private int mPageMargin = 10;

		private static PartImage JewelType01Image {
			get {
				if (_JewelTypeImage == null) {
					_JewelTypeImage = new PartImage();
					_JewelTypeImage.ImageSource = new DDSImage((byte[])Properties.Resources.uit_re_itemjewelslot01).BitmapImage;
					_JewelTypeImage.SourceRect = new Rectangle(0, 0, 64, 64);
					_JewelTypeImage.DestRect = new Rectangle(6, 6, 64, 64);
				}
				return _JewelTypeImage;
			}
		}
		private static PartImage _JewelTypeImage;


		[Browsable(true)]
		public Image BackgroundNineImage{
			get { return mBackgroundImage; }
			set {
				mBackgroundImage = value;
				Invalidate();
			}
		}

		public InfoOverlayForm() {
			InitializeComponent();
			this.SetStyle(ControlStyles.Selectable, false);
			BackgroundNineImage = Properties.Resources.window_backgroud;
			mDivider = new ImageBlock();
			mDivider.ImagePic = global::DnPakExplorer.Properties.Resources.itemchoicedlg;
			mDivider.Position = new System.Drawing.Point(12, 103);
			mDivider.Size = new System.Drawing.Size(190, 10);
			mDivider.SpriteDraw = true;
			mDivider.SpriteRect = new System.Drawing.Rectangle(30, 0, 80, 14);
			mDivider.SrcRect = new System.Drawing.Rectangle(0, 24, 140, 14);
			mItemNameFont = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
			this.TopMost = true;
		}

		#region 物品信息

		public static string GetPropertyText(List<Property> list, ref int i) {
			Property prop = list[i];
			int pid = (int)prop.id;
			if (pid==4 && i+1<list.Count && (int)list[i+1].id==5) {
				return PropertyUtil.GetPropertyName(32)+":"+prop.GetValueString()+"~"+list[++i].GetValueString()+"\n";
			} else if (pid==6 && i+1<list.Count && (int)list[i+1].id==7) {
				return PropertyUtil.GetPropertyName(33)+":"+prop.GetValueString()+"~"+list[++i].GetValueString()+"\n";
			} else if (pid==54 && i+1<list.Count && (int)list[i+1].id==55) {
				return PropertyUtil.GetPropertyName(32)+":"+prop.GetValueString()+"~"+list[++i].GetValueString()+"\n";
			} else if (pid==56 && i+1<list.Count && (int)list[i+1].id==57) {
				return PropertyUtil.GetPropertyName(33)+":"+prop.GetValueString()+"~"+list[++i].GetValueString()+"\n";
			} else if (PropertyUtil.IsPercentProperty(pid))
				return PropertyUtil.GetPropertyName(pid)+":"+prop.GetValueString()+"\n";
			else
				return PropertyUtil.GetPropertyName(pid)+":"+prop.GetValueString()+"\n";
		}

		public static string GetSkillText(PotencialRecord potencial) {
			switch (potencial.SkillUsingType) {
			case (int)SkillUsingType.Drug:
			case (int)SkillUsingType.NewSkill:
				return DnResourceUtil.GetSkillDescription(potencial.SkillId, potencial.SkillLevel).Replace("\\n", "\n");
			case (int)SkillUsingType.LevelUp:
				return "#y"+DnResourceUtil.GetSkillName(potencial.SkillId)+"+1";
			}
			return "";
		}

		public IItem Item{
			get { return mItem; }
			set {
				mItem = value;
				IItem item = mItem;
				BeginContent();
				mItemIcon = new ItemIcon();
				List<Property> list = null;

				#region Header Info
				mItemIcon.Item = item;
				mItemIcon.Position = new Point(140, 40);
				mItemIcon.BlockType = BlockType.Absolut;
				mItemIcon.Size = new Size(50, 50);
				AddBlock(mItemIcon);
				
				if ((item is IUserItem) && ((IUserItem)item).appliedEnchantLevel>0)
					AddText("+"+((IUserItem)item).appliedEnchantLevel+" "+item.name
						, Util.GetRankColor(item.rank), mItemNameFont);
				else
					AddText(item.name, Util.GetRankColor(item.rank), mItemNameFont);
				//this.itemIconBox1.Item = skill;
				AddText("#o限制等级:#w"+item.limitLevel.ToString()+"以上");
				AddText("#o级别:#w"+Util.GetRankText(item.rank));
				AddText("#o职业:#w"+item.needJobClassName);
				if(item.exchangType>0)
					AddText("#o类型:#w"+Util.GetExchangeName(item.exchangType));
				#endregion

				#region 基础属性
				list = item.BasePropertyList;
				if (list.Count>0) {
					AddDivider();
					for (int i=0; i<list.Count; i++) {
						AddText(GetPropertyText(list, ref i));
					}
				}
				#endregion

				if ((item is IUserItem)) {
					#region 宠物属性
					IUserItem userItem = (IUserItem)item;
					if (userItem.petLevelType > 0) {
						list = userItem.AppliedGrowProperty;
						if (list!=null && list.Count>0) {
							AddDivider();
							AddText("[宠物属性]", Color.Orange);
							string text = "";
							for (int i=0; i<list.Count; i++) {
								text += InfoOverlayForm.GetPropertyText(list, ref i);
							}
							AddText(text);
						}
					}
					#endregion

					#region 强化属性
					if (item.enchantId>0) {
						list = userItem.AppliedEnchantProperty;
						if (list != null && list.Count>0) {
							AddDivider();
							AddText("[强化属性]", Color.Orange);
							string text = "";
							for (int i=0; i<list.Count; i++) {
								text += GetPropertyText(list, ref i);
							}
							AddText(text);
						}
					}
					#endregion

					#region 制作属性
					if (item.typeParam1>0) {
						PotencialRecord potencial = userItem.AppliedPotential1Property;
						if (potencial!=null && potencial.Properties.Count>0) {
							string text = "";
							AddDivider();
							AddText("[制作属性]", Color.Orange);
							for (int i=0; i<potencial.Properties.Count; i++) {
								text += GetPropertyText(potencial.Properties, ref i);
							}
							AddText(text);
						}
						if (potencial!=null && potencial.SkillId>0) {
							AddText(GetSkillText(potencial));
						}
					}
					#endregion

					#region 附魔属性
					if (item.typeParam2 >= 0) {
						PotencialRecord potencial = userItem.AppliedPotential2Property;
						if (potencial!=null && potencial.Properties.Count>0) {
							string text = "";
							AddDivider();
							AddText("[附魔属性]", Color.Violet);
							for (int i=0; i<potencial.Properties.Count; i++) {
								text += GetPropertyText(potencial.Properties, ref i);
							}
							AddText(text);
						}
						if (potencial!=null && potencial.SkillId>0) {
							AddText(GetSkillText(potencial));
						}
					}
					#endregion

					#region 刻印属性
					if (item.imprintingType != ImprintingType.None) {
						ImprintingSlot imprintingSlot = ((IUserItem)item).AppliedImprintingSlot;
						if (imprintingSlot!=null && imprintingSlot.Item != null) {
							string text = "";
							AddDivider();
							AddText("[刻印属性]", Color.Orange);
							PropertySumer sumer = new PropertySumer();
							sumer.AddItem(imprintingSlot.Item);
							List<Property> imprintingProperties = sumer.ToList();
							for (int i=0; i<imprintingProperties.Count; i++) {
								text += GetPropertyText(imprintingProperties, ref i);
							}
							AddText(text);
							PotencialRecord potencial = imprintingSlot.Item.AppliedPotential1Property;
							if (potencial!=null && potencial.SkillId>0) {
								AddText(GetSkillText(potencial));
							}
						}
					}
					#endregion
				} else {
					#region 制作属性
					List<PotencialRecord> potencial1 = item.PotentialProperty1;
					if (potencial1!=null && potencial1.Count>0) {
						AddDivider();
						for (int i=0; i<potencial1.Count; i++) {
							PotencialRecord potencial = potencial1[i];
							AddDivider();
							AddText("[制作属性]-"+Math.Round(potencial1[i].Redio*100, 1)+"%", Color.Orange);
							List<Property> properties = potencial.Properties;
							for(int j=0; j<properties.Count; j++){
								AddText(GetPropertyText(properties, ref j));
							}
							if (potencial!=null && potencial.SkillId>0) {
								AddText(GetSkillText(potencial));
							}
						}
					}

					#endregion

					#region 附魔属性
					List<PotencialRecord> potencial2 = item.PotentialProperty2;
					if (potencial2!=null && potencial2.Count>0) {
						AddDivider();
						for (int i=0; i<potencial2.Count; i++) {
							PotencialRecord potencial = potencial2[i];
							AddDivider();
							AddText("[附魔属性]-"+Math.Round(potencial2[i].Redio*100, 1)+"%", Color.Violet);
							List<Property> properties = potencial2[i].Properties;
							for (int j=0; j<properties.Count; j++) {
								AddText(GetPropertyText(properties, ref j));
							}
							if (potencial!=null && potencial.SkillId>0) {
								AddText(GetSkillText(potencial));
							}
						}
					}

					#endregion

					#region 强化属性
					List<EnchantRecord> EnchantProperty = item.EnchantProperty;
					if (EnchantProperty != null && EnchantProperty.Count>0) {
						for (int i=0; i<EnchantProperty.Count; i++) {
							EnchantRecord record = EnchantProperty[i];
							StringBuilder sb = new StringBuilder();
							sb.AppendFormat("[强化{0}级]#g★#l{1}%", record.Level, Math.Round(record.SuccessRo*100, 1));
							if (record.BreakRo != 0)
								sb.AppendFormat("#r✸#l{0}%", Math.Round(record.BreakRo*100, 1));
							if (record.MinDown == 0 && record.MaxDown != 0)
								sb.AppendFormat("#v▼#l{0}", record.MaxDown);
							else if (record.MinDown != 0 && record.MaxDown != 0) {
								sb.AppendFormat("#v▼#l{0}~{1}", record.MinDown, record.MaxDown);
							}
							AddText(sb.ToString(), Color.OrangeRed, true, Font);

							List<Property> properties = record.Properties;
							for (int j=0; j<properties.Count; j++)
								AddText(GetPropertyText(properties, ref j));
						}
					}
					#endregion

					#region 刻印
					if (item.imprintingType != ImprintingType.None) {
						AddDivider();
						AddText("[刻印属性]", Color.Orange);
						AddText("可以应用"+DnResourceUtil.GetImprintTypeName(item.imprintingType)+"刻印属性");
					}
					#endregion
				}

				#region 成长精灵属性

				if (item.exchangType == ItemType.FairyCash && item.fairyType != FairyType.None) {
					Dntable table = DnResourceUtil.FairyGrowLevelTable;
					for (int r=0; r<table.RecordCount; r++) {
						if ((int)table[r, 1] == (int)item.fairyType) {
							AddDivider();
							AddText("#o[精灵"+(int)table[r, 0]+"级]");
							for (int c=3; c<18; c+=3) {
								int pid = (int)table[r, c];
								if (pid<0 || !Util.StateVlauePettern.IsMatch((string)table[r, c+1]) || !Util.StateVlauePettern.IsMatch((string)table[r, c+2]))
									break;
								float min = float.Parse((string)table[r, c+1]);
								float max = float.Parse((string)table[r, c+2]);
								if (min==0 && max == 0) 
									break;
								AddText(string.Format("{0}:{1}~{2}", PropertyUtil.GetPropertyName(pid), min, max));
							}
						}
					}
				}

				#endregion

				#region 龙玉
				if (item.slotsType >0 && item.slotsType<99) {
					AddDivider();
					AddText("[龙玉槽]", Color.Orange);
					AddJewelRow(item);

					if (item is IUserItem) {
						IUserItem userItem = (IUserItem)item;
						PropertySumer sumer = new PropertySumer();
						PotencialRecord skillPotencial = null;
						foreach (DragonJewelSlot slot in userItem.AppliedSlotsList) {
							if (slot.Item != null) {
								if (slot.DragonJewelSlotType == (int)DragonJewelType.Skill) {
									skillPotencial = slot.Item.AppliedPotential1Property;
								}
								foreach (Property p in slot.Item) {
									sumer.AddProperty(p);
								}
							}

							list = sumer.ToList();
							if (list != null && list.Count>0) {
								string textProp = "";
								for (int i=0; i<list.Count; i++) {
									Property prop = list[i];
									int pid = (int)prop.id;
									textProp += GetPropertyText(list, ref i);
								}
								AddText(textProp);
							}
						}
						if (skillPotencial!=null && skillPotencial.SkillId>0) {
							AddText(GetSkillText(skillPotencial));
						}
					}

				}
				#endregion

				#region 技能效果
				if (item.skillId > 0) {
					AddDivider();
					AddText("[技能效果]", Color.Orange);
					string dec = item.skillDecription;
					if (!String.IsNullOrEmpty(dec))
						AddText(dec.Replace("\\n", "\n"));
				}
				#endregion

				#region 套装
				if (item.set != null) {
					list = item.set.properties;
					if (list != null && list.Count > 0) {
						AddDivider();
						AddText("[套装效果]", Color.Orange);
						Character ch = DnPlayerUtil.CurrentCharacter;
						for (int i=0; i<list.Count; i++) {
							Property prop = list[i];
							int c = (int)prop.tag;
							string propText = null;
							if ((int)prop.id==4 && i+1<list.Count && (int)list[i+1].id%1000==5 && (int)list[i+1].tag==c) {
								propText = PropertyUtil.GetPropertyName(32)+":"+prop.GetValueString()+"~"+list[++i].GetValueString()+"\n";
							} else if ((int)prop.id==6 && i+1<list.Count && (int)list[i+1].id%1000==7 && (int)list[i+1].tag==c) {
								propText = PropertyUtil.GetPropertyName(33)+":"+prop.GetValueString()+"~"+list[++i].GetValueString()+"\n";
							} else if ((int)prop.id==54 && i+1<list.Count && (int)list[i+1].id%1000==55 && (int)list[i+1].tag==c) {
								propText = PropertyUtil.GetPropertyName(32)+":"+prop.GetValueString()+"~"+list[++i].GetValueString()+"\n";
							} else if ((int)prop.id==56 && i+1<list.Count && (int)list[i+1].id%1000==57 && (int)list[i+1].tag==c) {
								propText = PropertyUtil.GetPropertyName(33)+":"+prop.GetValueString()+"~"+list[++i].GetValueString()+"\n";
							} else
								propText = PropertyUtil.GetPropertyName((int)prop.id)+":"+prop.GetValueString()+"\n";
							AddText(c+"套 "+propText, ch!=null&&ch.EquipmentPanel.GetSetItemCount(item.setId)>=c?Color.White:Color.Gray);
						}
					}

					AddDivider();
					AddText("[套装]", Color.Orange);
					int jobId = 0;
					foreach (string jonstring in item.needJobClass.Split(';')) {
						if (jonstring != "") {
							jobId = int.Parse(jonstring);
							break;
						}
					}
					foreach (IItem it in item.set.setItems) {
						if (Util.JobCanAccepet(jobId, it.needJobClass))
							AddText(it.name, Color.White);
					}
					if (!String.IsNullOrEmpty(item.set.setDescription)) {
						AddText(item.set.setDescription, Color.Blue);
					}
				}
				#endregion

				#region 物品描述
				if (!String.IsNullOrEmpty(item.description)) {
					AddDivider();
					AddText(item.description.Replace("\\n", "\n"));
				}
				#endregion

				EndContent();
				//Refresh();

				Repaint();
			}

			
		}

		#endregion

		#region 技能信息

		public Skill Skill {
			get {
				return mSkill;
			}
			set {
				mSkill = value;
				BeginContent();
				AddText(mSkill.Name, Color.White, mItemNameFont);
				AddText("等级："+mSkill.Level);
				AddText("最大等级："+mSkill.MaxLevel);
				AddText("类型："+mSkill.SkillType);
				AddText("职业："+Util.GetJobName(mSkill.NeedJob));
				if (mSkill.NeedWeaponType1>=0) {
					AddText("需要武器类型："+mSkill.NeedWeaponType1);
				}
				if (mSkill.NeedWeaponType2>=0) {
					AddText("需要武器类型："+mSkill.NeedWeaponType2);
				}
				string desc = mSkill.SkillDescrition;
				if (!String.IsNullOrEmpty(desc)) {
					AddDivider();
					AddText(desc.Replace("\\n", "\n"));
				}
				
				int i = 0;
				foreach (SkillEffect e in mSkill) {
					if (i == 0) {
						AddDivider();
					}
					AddText("#j[效果"+i+"]");
					AddText("持续时间："+Util.DuriationMillToString(e.Duration));
					AddText("效果ID："+e.EffectClass);
					AddText("效果类型："+e.EffectClassType);
					AddText("效果值："+e.EffectClassValue);
				}
				EndContent();
				Repaint();
			}
		}

		#endregion

		public void BeginContent() {
			mTmpContent = new List<DrawingBlock>();
			mTmpStartPoint = mStartOffset;
		}

		public void EndContent() {
			mTexts = mTmpContent;
			int maxRight = mPageSize.Width;
			int maxBottom = 0;
			foreach (DrawingBlock ta in mTexts) {
				if (ta.BlockType == BlockType.Absolut)
					continue;
				if (ta.Rect.Bottom > maxBottom)
					maxBottom = ta.Rect.Bottom;
				if (ta.Rect.Right > maxRight)
					maxRight = ta.Rect.Right;
			}
			ClientSize = new Size(maxRight+13, maxBottom+13);
		}

		public void AddDivider() {
			ImageBlock ib = new ImageBlock();
			ib.ImagePic = mDivider.ImagePic;
			ib.SpriteDraw = mDivider.SpriteDraw;
			ib.SpriteRect = mDivider.SpriteRect;
			ib.SrcRect = mDivider.SrcRect;
			ib.Size = mDivider.Rect.Size;
			ib.Position = mTmpStartPoint;
			AddBlock(ib);
		}

		public void AddText(string text) {
			AddText(text, ForeColor);
		}

		public void AddText(string text, Color textColor) {
			AddText(text, textColor, false, Font);
		}

		public void AddText(string text, Color textColor, Font font) {
			AddText(text, textColor, false, font);
		}

		public void AddText(string text, Color textColor, bool oneLine, Font font) {
			StringFormat sf = new StringFormat();
			//sf.FormatFlags = StringFormatFlags.LineLimit;
			if(!String.IsNullOrEmpty(text)) {
				Rectangle rect = GetRestContectRect();
				List<RichTextDrawBlock.RichString> list = RichTextDrawBlock.Measure(
					RichTextDrawBlock.Parse(text, font, textColor),
					this.CreateGraphics(), sf, rect);

				List<RichTextDrawBlock.RichString> rsList = null;
				int bo = rect.Bottom;
				for (int i=0; i<list.Count; i++) {
					RichTextDrawBlock.RichString rs = list[i];
					if (rs.rect.Bottom>bo) {
						if (rsList != null) {
							AddBlock(new RichTextDrawBlock(rsList));
							rsList = null;
						}
						MoveNextPage();
						rect = GetRestContectRect();
						bo += rect.Height;
					}

					if (rsList == null)
						rsList = new List<RichTextDrawBlock.RichString>();
					rsList.Add(rs);
				}
				if (rsList != null) {
					AddBlock(new RichTextDrawBlock(rsList));
					rsList = null;
				}
			}
		}

		public void AddJewelRow(IItem item) {
			AddBlock(new JewelSlotsBlock(item, mTmpStartPoint));
		}

		public void MoveNextPage() {
			mTmpStartPoint.X += mPageSize.Width + mPageMargin;
			mTmpStartPoint.Y = mStartOffset.Y;
		}

		public void AddBlock(DrawingBlock block) {
			if (block.BlockType == BlockType.Block) {
				if (mTmpStartPoint.Y + block.Size.Height > mStartOffset.Y+mPageSize.Height) {
					MoveNextPage();
				}
				block.Position = mTmpStartPoint;
				mTmpContent.Add(block);
				mTmpStartPoint.Y += block.Size.Height;
			} else {
				mTmpContent.Add(block);
			}
		}

		private Rectangle GetRestContectRect() {
			return new Rectangle(mTmpStartPoint, new Size(mPageSize.Width, mPageSize.Height+mStartOffset.Y-mTmpStartPoint.Y));
		}

		private void InfoOverlayForm_Paint(object sender, PaintEventArgs e) {
			Repaint(e.Graphics);
		}

		protected override void OnPaint(PaintEventArgs e) {
			//base.OnPaint(e);
		}

		private void Repaint(Graphics g) {
			if (BackgroundNineImage != null) {
				if (!true) {
					g.FillRectangle(new SolidBrush(Color.FromArgb(200, 0, 0, 0)), new Rectangle(
					Padding.Left,
					Padding.Right,
					ClientRectangle.Right - Padding.Horizontal,
					ClientRectangle.Bottom - Padding.Vertical));
				}
				Sprite.Draw(g, mBackgroundImage, ClientRectangle, Padding);
			}
			if (mTexts != null) {
				foreach (DrawingBlock text in mTexts) {
					text.Draw(g);
				}
			}
		}


		protected override CreateParams CreateParams {
			get {
				CreateParams cp  =   base.CreateParams;
				cp.ExStyle  |=   0x00080000;  //  WS_EX_LAYERED 扩展样式
				return cp;
			}
		}

		public void Repaint() {
			Repaint(alpha);
		}

		public void SetAlpha(byte algha) {

			try {
				Win32.Size size  =   new Win32.Size(Width, Height);
				Win32.Point pointSource  =   new Win32.Point(0, 0);
				Win32.Point topPos  =   new Win32.Point(Left, Top);
				Win32.BLENDFUNCTION blend  =   new Win32.BLENDFUNCTION();
				blend.BlendOp              =  Win32.AC_SRC_OVER;
				blend.BlendFlags           =   0;
				blend.SourceConstantAlpha  =  algha;
				blend.AlphaFormat          =  Win32.AC_SRC_ALPHA;

				Win32.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0, ref  blend, Win32.ULW_ALPHA);
			} finally {
			}
		}

		public void Repaint(byte algha) {
			IntPtr screenDc  =  Win32.GetDC(IntPtr.Zero);


			IntPtr memDc  =  Win32.CreateCompatibleDC(screenDc);
			IntPtr hBitmap  =  IntPtr.Zero;
			IntPtr oldBitmap  =  IntPtr.Zero;

			try {
				//Bitmap bmp = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); 

				//hBitmap  =  bitmap.GetHbitmap(Color.FromArgb(0));   // 创建GDI位图句柄，效率较低
				//hBitmap = bmp.GetHbitmap(Color.FromArgb(0));
				hBitmap = Win32.CreateBitmap(Width, Height, 1, 32, IntPtr.Zero);

				oldBitmap  =  Win32.SelectObject(memDc, hBitmap);
				Win32.Size size  =   new Win32.Size(Width, Height);
				Win32.Point pointSource  =   new Win32.Point(0, 0);
				Win32.Point topPos  =   new Win32.Point(Left, Top);
				Win32.BLENDFUNCTION blend  =   new Win32.BLENDFUNCTION();
				blend.BlendOp              =  Win32.AC_SRC_OVER;
				blend.BlendFlags           =   0;
				blend.SourceConstantAlpha  =  algha;
				blend.AlphaFormat          =  Win32.AC_SRC_ALPHA;

				Graphics g = Graphics.FromHdc(memDc);
				Repaint(g);


				Win32.UpdateLayeredWindow(Handle, screenDc, ref  topPos, ref  size, memDc, ref  pointSource, 0, ref  blend, Win32.ULW_ALPHA);
			} finally {
				Win32.ReleaseDC(IntPtr.Zero, screenDc);
				if (hBitmap  !=  IntPtr.Zero) {
					Win32.SelectObject(memDc, oldBitmap);

					Win32.DeleteObject(hBitmap);
				}
				Win32.DeleteDC(memDc);
			}
		}

		private void InfoOverlayForm_VisibleChanged(object sender, EventArgs e) {
			if (this.Visible) {
				if (!timer1.Enabled) {
					timer1.Start();
				}
				//AnimateWindow(this.Handle, 1000, 0x20010);   // 居中逐渐显示。
				//Util.AnimateWindow(this.Handle, 100, 0xA0000);
				//AnimateWindow(this.Handle, 1000, 0x60004); // 自上向下。
				//AnimateWindow(this.Handle, 1000, 0x20004); // 自上向下。
			} else {
				//AnimateWindow(this.Handle, 1000, 0x10010);    // 居中逐渐隐藏。
				//Util.AnimateWindow(this.Handle, 500, 0x90000); // 淡入淡出效果。
				//AnimateWindow(this.Handle, 1000, 0x50008); // 自下而上。
				//AnimateWindow(this.Handle, 1000, 0x10008); // 自下而上。
			}
		}

		private void InfoOverlayForm_Load(object sender, EventArgs e) {
			//Util.AnimateWindow(this.Handle, 500, 0xA0000);
		}

		private void InfoOverlayForm_FormClosing(object sender, FormClosingEventArgs e) {
			//Util.AnimateWindow(this.Handle, 500, 0x90000); // 淡入淡出效果。
		}

		byte alpha = 255;
		private void timer1_Tick(object sender, EventArgs e) {

			//if (ToShow) {
			//	Util.SetWindowPos(this.Handle, new IntPtr(Util.HWND_TOP), 0, 0, 0, 0, Util.SWP_NOACTIVATE|Util.SWP_NOMOVE|Util.SWP_NOSIZE|Util.SWP_NOREDRAW);
			//	Util.ShowWindow(this.Handle, Util.SW_SHOWNOACTIVATE);
			//} else {
			//	base.Hide();
			//}
			//return;
			if (ToShow) {
				if (!this.Visible) {
					Win32.SetWindowPos(this.Handle, new IntPtr(Win32.HWND_TOP), 0, 0, 0, 0, Win32.SWP_NOACTIVATE|Win32.SWP_NOMOVE|Win32.SWP_NOSIZE|Win32.SWP_NOREDRAW);
					Win32.ShowWindow(this.Handle, Win32.SW_SHOWNOACTIVATE);
				} else {

					//alph += 25;

					//Win32.SetLayeredWindowAttributes(this.Handle, 0, alph, Win32.ULW_ALPHA);
					double o = this.MYOpacity;
					o += 0.1;
					if (o>1) {
						o = 1;
					}
					this.MYOpacity = o;
				}
			} else if (!ToShow) {
				if (this.Visible) {
					
					//Win32.SetLayeredWindowAttributes(this.Handle, 0, alph, Win32.ULW_ALPHA);
					//if (alph <=80) {
					//	//this.Hide();
					//} else {
					//	alph -= 25;
					//}
					double o = this.MYOpacity;
					o -= 0.1;
					if (o<0) {
						o = 0;
						base.Hide();
					}
					this.MYOpacity = o;
				}
			}
		}

		double op = 1;
		double MYOpacity{
			get{
				return op;
			}
			set{
				op = value;
				byte a = (byte)(op*255);
				if (alpha != a) {
					SetAlpha(a);
				}
				alpha = a;
			}
		}

		public class DrawingBlock {
			public Point Position;
			public Size Size;
			public BlockType BlockType = BlockType.Block;

			public Rectangle Rect {
				get { return new Rectangle(Position, Size); }
			}

			public virtual void Draw(Graphics g) {

			}
		}

		public enum BlockType {
			Block, Absolut
		}

		class ItemIcon : DrawingBlock {

			public IItem Item;

			public override void Draw(Graphics g) {
				if (Item != null) {
					if (Item.iconId >= 0) {
						Util.DrawItemImage(Item.iconId, Rect, g);
					}
					if (Item.rank >= 0 && Item.rank<=6) {
						Util.DrawItemBox(Item.rank, Rect, g);
					}
					if(Item is IUserItem)
						Util.DrawItemTags((IUserItem)Item, Rect, g);
				}
			}
		}

		public class TextArea : DrawingBlock {
			public Font font;
			public Color color;
			public string text;
			public StringFormat sf;

			public override void Draw(Graphics g) {
				g.DrawString(text, font, new SolidBrush(color), Rect, sf);
			}
		}

		public class RichTextDrawBlock : TextArea {
			List<RichString> mRichStrings;

			public RichTextDrawBlock(List<RichString> richString) {
				mRichStrings = richString;
				if (mRichStrings.Count>0) {
					RectangleF rect = mRichStrings[0].rect;
					foreach (RichString rs in mRichStrings) {
						if (rs.rect.X<rect.X) {
							rect.X = rs.rect.X;
						}
						if (rs.rect.Y<rect.Y) {
							rect.Y = rs.rect.Y;
						}
						if (rs.rect.Right>rect.Right) {
							rect.Width = rs.rect.Right-rect.X;
						}
						if (rs.rect.Bottom>rect.Bottom) {
							rect.Height = rs.rect.Bottom-rect.Y;
						}
					}
					Size = new Size((int)rect.Width, (int)rect.Height);
				}
			}

			public static string ToHtml(List<RichString> richStrings) {
				StringBuilder sb = new StringBuilder();
				foreach (RichString rs in richStrings) {
					sb.AppendFormat("<span style=\"color:{0}\">{1}</span>", ColorTranslator.ToHtml(rs.color), rs.text);
				}
				return sb.ToString();
			}

			public static List<RichString> Parse(string text, Font font, Color color) {
				int lastIndex = 0;
				int parseIndex = 0;
				int index = 0;
				int stringLength = text.Length;
				List<RichString> richStrings = new List<RichString>();
				Color nextColor = color;
				while (parseIndex < stringLength && (index = text.IndexOf('#', parseIndex)) >= 0) {
					parseIndex = index + 1;
					if (parseIndex < stringLength) {
						Color c = Util.CharToColor(text[parseIndex]);
						if (c != Color.Empty) {
							nextColor = c;
							parseIndex++;
						}else
							continue;
					}
					if (lastIndex < index) {
						RichString rs = new RichString();
						rs.font = font;
						rs.color = color;
						rs.text = text.Substring(lastIndex, index - lastIndex);
						richStrings.Add(rs);
						lastIndex = index + 2;
					} else if (lastIndex==index) {
						lastIndex += 2;
					}
					color = nextColor;
				}
				index = stringLength;
				if (lastIndex < index) {
					RichString rs = new RichString();
					rs.font = font;
					rs.color = color;
					rs.text = text.Substring(lastIndex, index - lastIndex);
					richStrings.Add(rs);
					lastIndex = index + 2;
				}
				return richStrings;
			}

			public static List<RichString> Measure(List<RichString> richStrings, Graphics g, StringFormat sf, Rectangle rect) {
				List<RichString> list = new List<RichString>();
				if (richStrings.Count<=0)
					return list;
				PointF startPoint = rect.Location;
				float height = g.MeasureString("测试", richStrings[0].font).Height;
				for (int i = 0; i < richStrings.Count; i++) {
					int chars = 0;
					int lines = 0;
					string str = richStrings[i].text;
					float extraLineSpace = -1.5f;
					while (true) {
						SizeF textSize = g.MeasureString(str, richStrings[i].font, new SizeF(rect.Right - startPoint.X, height), sf, out chars, out lines);
						height = textSize.Height;

						if (startPoint.X + textSize.Width > rect.Right) {
							// 没有足够空间，换行重新计算
							startPoint.Y += height+extraLineSpace;
							startPoint.X = rect.X;
							continue;
						}

						//if (startPoint.X>=Rect.Bottom) {
						//	// 没有足够空间，
						//	break;
						//}

						// 测量已确认

						string stringToDraw = str.Substring(0, chars);

						RichString rs = new RichString();
						rs.color = richStrings[i].color;
						rs.font = richStrings[i].font;
						rs.text = stringToDraw;
						rs.rect = new RectangleF(startPoint.X, startPoint.Y, textSize.Width, height);
						list.Add(rs);

						startPoint.X += textSize.Width-4;
						str = str.Substring(chars);		// 下一个字符串

						if (str == "") {	// 画完
							if (stringToDraw.EndsWith("\n")) {
								startPoint.Y += height+extraLineSpace;
								startPoint.X = rect.X;
							}
							break;
						} else {			// 未画完，新行继续
							startPoint.Y += height+extraLineSpace;
							startPoint.X = rect.X;
						}
					}
				}
				return list;
			}

			public override void Draw(Graphics g) {
				if (mRichStrings.Count>0) {
					SolidBrush brush = new SolidBrush(Color.Empty);
					Point start = new Point((int)mRichStrings[0].rect.Location.X, (int)mRichStrings[0].rect.Location.Y);
					if (start != Position) {
						int dx = Position.X - start.X;
						int dy = Position.Y - start.Y;
						foreach (RichString rs in mRichStrings) {
							rs.rect.X += dx;
							rs.rect.Y += dy;
						}
					}
					foreach (RichString rs in mRichStrings) {
						brush.Color = rs.color;
						g.DrawString(rs.text, rs.font, brush, rs.rect.Location);
					}
				}
			}

			public class RichString {
				public Font font;
				public string text;
				public Color color;
				public RectangleF rect;
			}
		}

		class JewelSlotsBlock : DrawingBlock{
			List<DragonJewelSlotBox> mSlots = new List<DragonJewelSlotBox>();

			public JewelSlotsBlock(IItem item, Point startPoint) {
				Size.Width = 0;
				PartImage backImage = new PartImage();
				backImage = new PartImage();
				backImage.ImageSource = new DDSImage((byte[])Properties.Resources.uit_item_slot04).BitmapImage;
				backImage.SourceRect = new Rectangle(2, 2, 50, 50);
				backImage.DestRect = new Rectangle(0, 0, 50, 50);
				if (item is IUserItem) {
					foreach (DragonJewelSlot dj in ((IUserItem)item).AppliedSlotsList) {
						DragonJewelSlotBox slot = new DragonJewelSlotBox();
						slot.Bounds = new Rectangle(startPoint, new Size(47, 47));
						slot.TargetSlot = dj;
						slot.ItemDestRect = new Rectangle(-2, -2, 50, 50);
						slot.Background = backImage;
						slot.TypeImage = new PartImage();
						slot.TypeImage.ImageSource = Util.GetJewelTypeImage(dj.DragonJewelSlotType);
						slot.TypeImage.SourceRect = new Rectangle(0, 0, 50, 50);
						slot.TypeImage.DestRect = new Rectangle(2, 2, 50, 50);
						mSlots.Add(slot);
						startPoint.X += slot.Bounds.Width;
						Size = slot.Bounds.Size;
					}
				} else {
					foreach (int dj in item.slotTypes) {
						DragonJewelSlotBox slot = new DragonJewelSlotBox();
						slot.Bounds = new Rectangle(startPoint, new Size(47, 47));
						slot.TargetSlot = null;
						slot.ItemDestRect = new Rectangle(-2, -2, 50, 50);
						slot.Background = backImage;
						slot.TypeImage = new PartImage();
						slot.TypeImage.ImageSource = Util.GetJewelTypeImage(dj);
						slot.TypeImage.SourceRect = new Rectangle(0, 0, 50, 50);
						slot.TypeImage.DestRect = new Rectangle(2, 2, 50, 50);
						mSlots.Add(slot);
						startPoint.X += slot.Bounds.Width;
						Size = slot.Bounds.Size;
					}
				}
				
			}

			public override void Draw(Graphics g) {
				foreach (DragonJewelSlotBox slot in mSlots) {
					Point offset = slot.Position;
					g.TranslateTransform(offset.X, offset.Y);
					slot.OnDraw(g);
					g.TranslateTransform(-offset.X, -offset.Y);
					//g.DrawRectangle(Pens.White, slot.Bounds);
				}
			}
		}

		class ImageBlock : DrawingBlock {
			public Image ImagePic { get; set; }

			public Rectangle SrcRect { get; set; }

			public bool SpriteDraw { get; set; }

			public Rectangle SpriteRect { get; set; }

			public override void Draw(Graphics g) {
				if (ImagePic != null) {
					if (SpriteDraw)
						Sprite.Draw(g, ImagePic, Rect,
							new Rectangle(SrcRect.X+SpriteRect.X, SrcRect.Y+SpriteRect.Y, SpriteRect.Width, SpriteRect.Height), SrcRect);
					else
						g.DrawImage(ImagePic, Rect, SrcRect, GraphicsUnit.Pixel);
				}
			}
		}

		private static InfoOverlayForm mInfoForm;

		public static InfoOverlayForm GetOrCreateItemInfoForm() {
			if (mInfoForm == null || mInfoForm.IsDisposed) {
				mInfoForm = new InfoOverlayForm();
			}
			return mInfoForm;
		}

		public static void ShowItem(IUserItem item, bool forceUpdate=false){
			InfoOverlayForm form = GetOrCreateItemInfoForm();
			if (forceUpdate || item != form.Item) {
				form.Item = item;
			}
			form.UpdateInfoFormPosition();
			form.Show();
		}

		public static void ShowItem(Skill skill, bool forceUpdate=false) {
			InfoOverlayForm form = GetOrCreateItemInfoForm();
			if (forceUpdate || skill != form.Skill) {
				form.Skill = skill;
			}
			form.UpdateInfoFormPosition();
			form.Show();
		}

		public static void HideItem() {
			InfoOverlayForm form = GetOrCreateItemInfoForm();
			form.Hide();
		}

		public new void Show() {
		//	Util.ShowWindow(this.Handle, 4);
			this.TopLevel = true;
			this.ToShow = true;
		}

		public new void Show(IWin32Window parent) {
			Show();
		}

		public new void Hide() {
			ToShow = false;
		}

		public void UpdateInfoFormPosition() {
			Rectangle bounds = this.DesktopBounds;
			bounds.Location = new Point(Cursor.Position.X+1, Cursor.Position.Y);
			if (bounds.Bottom > Screen.PrimaryScreen.WorkingArea.Height) {
				bounds.Y = Screen.PrimaryScreen.WorkingArea.Height-bounds.Height;
			}
			if (bounds.Right > Screen.PrimaryScreen.WorkingArea.Width && Screen.PrimaryScreen.WorkingArea.Width/2<bounds.X) {
				bounds.X = bounds.X - bounds.Width;
			}
			this.DesktopLocation = bounds.Location;
		}

		private void InfoOverlayForm_SizeChanged(object sender, EventArgs e) {
			Repaint();
		}
	}
}
